package org.dna.metronomo.persistence;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

/**
 * Static inner class to verify and create DB schema
 * */
public class DBInit {
    static {
        //configure logging
        URL url = ClassLoader.getSystemResource("log4j.properties");
        PropertyConfigurator.configure(url);
    }
    

    private static final String DB_SCHEMA_PATH = "org/dna/metronomo/persistence/ddl/hsql/metronomo-schema.sql";
    private static final String DB_INITSCRIPT_PATH = "org/dna/metronomo/persistence/ddl/hsql/metronomo-init.sql";
    public static String DRIVER;
    public static String USERNAME;
    public static String PASSWORD;
    public static String URL;
    protected static boolean s_schemaInitialized;
    private static final Logger LOG = Logger.getLogger("org.dna.metronomo.persistence");

    public static void scriptRunner(Connection conn, String scriptName) throws IOException, SQLException {
        ScriptRunner runner = new ScriptRunner(conn);
        StringWriter errStringWriter = new StringWriter();
        PrintWriter errorPrintw = new PrintWriter(errStringWriter);
        StringWriter logStringWriter = new StringWriter();
        PrintWriter logPrintw = new PrintWriter(logStringWriter);

        runner.setErrorLogWriter(errorPrintw);
        runner.setLogWriter(logPrintw);

        runner.runScript(Resources.getResourceAsReader(scriptName));
        LOG.error(errStringWriter.toString());
        LOG.info(logStringWriter.toString());
    }
    
    private synchronized static void createSchema(Connection conn) throws PersistenceException {
        if (s_schemaInitialized) {
            LOG.info("schema already created");
            return;
        }

//		Connection conn = null;
//		try {
//			conn = m_sqlSessionFactory.getConfiguration().getEnvironment()
//					.getDataSource().getConnection();
//		} catch (SQLException e) {
//			LOG.warning("Error retrieving the connection");
//			return;
//		}
        try {
            conn.createStatement().execute("SELECT * FROM User");
            LOG.info("database schema exists, normal startup");
        } catch (SQLException sqle) {
            LOG.error("expected database schema does not exist, will "
                    + "create. Error is: " + sqle.getMessage());
            try {
                scriptRunner(conn, DB_SCHEMA_PATH);
                scriptRunner(conn, DB_INITSCRIPT_PATH);
            } catch (IOException e) {
                LOG.error("Error in creating DB schema, file error" + e);
                throw new PersistenceException(e);
            } catch (SQLException e) {
                LOG.error("Error in creating DB schema, sql error" + e);
                throw new PersistenceException(e);
            }

            // create new admin User
            // LOG("inserting default admin user into database");
            LOG.info("schema creation complete");
        }
        s_schemaInitialized = true;
    }

    public static void createSchema() {
        try {
            Properties props = Resources.getResourceAsProperties("org/dna/metronomo/persistence/db.properties");
            URL = props.getProperty("url") + ":" + props.getProperty("db.type")
                    + ":" + props.getProperty("db.name");
            DRIVER = props.getProperty("driver");
            USERNAME = props.getProperty("username");
            PASSWORD = props.getProperty("password");
            Class.forName(DRIVER).newInstance();
            Connection conn = DriverManager.getConnection(URL, USERNAME,
                    PASSWORD);

            try {
                createSchema(conn);
            } finally {
                conn.close();
            }
        } catch (Exception e) {
            throw new RuntimeException("Description.  Cause: " + e, e);
        }
    }
}
